package com.scunewscreeper.service.news.impl;

import com.alibaba.fastjson.JSON;
import com.scunewscreeper.config.RedisConfig;
import com.scunewscreeper.config.Status;
import com.scunewscreeper.entity.DataTNews;
import com.scunewscreeper.entity.StarTNews;
import com.scunewscreeper.entity.StartNewsPK;
import com.scunewscreeper.exception.ExceptionManager;
import com.scunewscreeper.repository.DataTNewsRepository;
import com.scunewscreeper.repository.SessionTKeyRepository;
import com.scunewscreeper.repository.StarTNewsRepository;
import com.scunewscreeper.service.authority.AuthorityService;
import com.scunewscreeper.service.news.NewsService;
import com.scunewscreeper.util.RandomUtil;
import com.scunewscreeper.util.RedisUtil;
import com.scunewscreeper.vo.HistoryViewVO;
import com.scunewscreeper.vo.NewsDetailVO;
import com.scunewscreeper.vo.NewsInfoVO;
import com.scunewscreeper.vo.StarNewsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.transaction.Transactional;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class NewsServiceImpl implements NewsService {
    private Integer pageSize=10;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    DataTNewsRepository dataRepo;
    @Autowired
    SessionTKeyRepository sessionRepo;
    @Autowired
    AuthorityService authorityService;
    @Autowired
    StarTNewsRepository starNewsRepo;

    @Override
    @Transactional
    public Object GetNewsList(int page, String type, String source) {
        try{
            List<NewsInfoVO> resultList;
            Pageable pageable= PageRequest.of(page,pageSize);
            Page<DataTNews> page1=null;
            List<DataTNews> dataTNewsList;
            do{
                // 全部
                if(!StringUtils.hasText(type)&&!StringUtils.hasText(source)){
                    page1 = dataRepo.findAllByPageable(pageable);
                    break;
                }
                // by source
                if(!StringUtils.hasText(type)){
                    page1 = dataRepo.findByDSourcePageable(source,pageable);
                    break;
                }
                // by type
                if(!StringUtils.hasText(source)){
                    page1=dataRepo.findByDTypePageable(type,pageable);
                    break;
                }
                // by source and type
                if(StringUtils.hasText(source)&&StringUtils.hasText(type)){
                    page1=dataRepo.findByDTypeAndDSourcePageable(type,source,pageable);
                    break;
                }

            }while (false);
            dataTNewsList=page1.getContent();
            resultList=GetDataInfoList(dataTNewsList);
            return JSON.toJSON(resultList);
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    @Transactional
    /**
     * 获取新闻详情
     * @param newsId
     * @param token
     * @param openId
     * @return java.lang.Object
     */
    public Object GetNewsDetail(String newsId,String token,String openId) {
        try {
            DataTNews targetNew=dataRepo.findBydId(newsId);
            if(targetNew==null){
                throw ExceptionManager.create(Status.CustomErrors.DataNotExist.getErrorCode(), Status.CustomErrors.DataNotExist.getErrorMsg());
            }
            // 更新浏览量
            UpdateReadNum(RedisConfig.redisReadNumKey,newsId);
            // 插入历史浏览记录
            if(!authorityService.IsAnoymousUser(openId)){
                String redisKey= RedisConfig.historyViewKey+openId;
                RecordHistoryView(redisKey,newsId);
            }
            boolean hasStar=HasStar(newsId,openId);
            NewsDetailVO detailVO=new NewsDetailVO(
                    targetNew.getDId(),
                    targetNew.getDSource(),
                    targetNew.getDType(),
                    targetNew.getDTitle(),
                    targetNew.getDSubdate().toString(),
                    targetNew.getDContent(),
                    targetNew.getDUrl(),
                    targetNew.getDLikeNum(),
                    targetNew.getDReadNum(),
                    hasStar
            );
            return detailVO;
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    @Transactional
    public Object StarNews(String newsId, String openId) {
        try {
            DataTNews dataTNews = dataRepo.findBydId(newsId);
            if (dataTNews == null) {
                throw ExceptionManager.create(Status.CustomErrors.DataNotExist.getErrorCode(), Status.CustomErrors.DataNotExist.getErrorMsg());
            }
            StarTNews starTNews=starNewsRepo.findStarTNewsByNewsIdAndOpenId(newsId, openId);
            if(starTNews==null){
                StarTNews newStarNews=new StarTNews(
                        new StartNewsPK(openId,newsId),
                        new Timestamp(System.currentTimeMillis()));
                starNewsRepo.save(newStarNews);
                return 0;
            }else{
                starNewsRepo.delete(starTNews);
                return 1;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw ExceptionManager.create(Status.CustomErrors.DataBaseError.getErrorCode(), Status.CustomErrors.DataBaseError.getErrorMsg());
        }
    }

    @Override
    @Transactional
    public Object GetStarNewsList(String openId) {
        try {
            List<StarNewsVO> starTNewsList=starNewsRepo.GetStarNews(openId);
            if(starTNewsList==null){
                return 1;
            }else {
                return JSON.toJSON(starTNewsList);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    @Transactional
    public Object LikeNews(String newsId) {
        try {
            DataTNews dataTNews = dataRepo.findBydId(newsId);
            if (dataTNews == null) {
                throw ExceptionManager.create(Status.CustomErrors.DataNotExist.getErrorCode(), Status.CustomErrors.DataNotExist.getErrorMsg());
            }
            dataRepo.UpdateLikeNum(newsId,1);
            return 0;
        }catch (Exception e){
            e.printStackTrace();
            throw ExceptionManager.create(Status.CustomErrors.DataBaseError.getErrorCode(), Status.CustomErrors.DataBaseError.getErrorMsg());
        }
    }

    /**
     * 查看用户浏览记录
     * @param openId
     * @return java.lang.Object
     */
    @Override
    public Object GetHistoryViews(String openId) {
        try {
            String key=RedisConfig.historyViewKey+openId;
            List<HistoryViewVO> historyViewVOList=new ArrayList<HistoryViewVO>();
            if(redisUtil.hasKey(key)){
                List<Object> historyList= redisUtil.lGet(key,0,redisUtil.lGetListSize(key));
                for(Object newsId:historyList){
                    historyViewVOList.add(dataRepo.GetHistoryVoByNewsId(newsId.toString()));
                }
                Collections.reverse(historyViewVOList);
                return JSON.toJSON(historyViewVOList);
            }else{
                return null;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }
    
    /**
     * 获取轮播图
     * @param openId
     * @return java.lang.Object
     */
    @Override
    public Object GetStickyNews(String openId) {
        try{
            int page= RandomUtil.RandomInt(0,2);
            List<NewsInfoVO> resultList;
            Pageable pageable= PageRequest.of(page,pageSize);
            Page<DataTNews> page1=null;
            List<DataTNews> dataTNewsList;
            // 全部
            int low=RandomUtil.RandomInt(2,3);
            int up=RandomUtil.RandomInt(5,2);
            page1 = dataRepo.findAllByPageable(pageable);
            dataTNewsList=page1.getContent();
            resultList=GetDataInfoList(dataTNewsList);
            return JSON.toJSON(resultList.subList(low,up));
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 判断用户是否收藏该文章
     * @param newsId
     * @param openId
     * @return boolean
     */
    private boolean HasStar(String newsId,String openId){
        StarTNews starTNews=starNewsRepo.findStarTNewsByNewsIdAndOpenId(newsId, openId);
        if(starTNews==null){
            return false;
        }else{
            return true;
        }
    }
    /**
     * 历史记录生成策略
     * @param key
     * @param newsId
     * @return void
     */
    private void RecordHistoryView(String key,String newsId){
        try {
            if(redisUtil.hasKey(key)){
                while (redisUtil.lGetListSize(key)>20){
                    redisUtil.lRemoveLeft(key);
                }
                redisUtil.lRemove(key,1,newsId);
                // 时间刷新
                redisUtil.lSet(key,newsId,RedisConfig.HISTORY_LIVE_TIME);
            }else{
                redisUtil.lSet(key,newsId,RedisConfig.HISTORY_LIVE_TIME);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }
//    private List<StarNewsVO> GetStarNewsList(List<StarTNews> rawList){
//        List<StarNewsVO> resultList=new ArrayList<>();
//        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//        for(StarTNews news:rawList){
//            resultList.add(new StarNewsVO(
//                    news.getSId().getSNewsid(),
//                    sdf.format(news.getSStarttime())
//            ));
//        }
//        return resultList;
//    }
    /**
     * 生成新闻信息列表
     * @param rawList
     * @return java.util.List<com.scunewscreeper.vo.NewsInfoVO>
     */
    private List<NewsInfoVO> GetDataInfoList(List<DataTNews> rawList){
        List<NewsInfoVO> resultList=new ArrayList<NewsInfoVO>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for(DataTNews news : rawList){
            resultList.add(new NewsInfoVO(
                    news.getDId(),
                    news.getDSource(),
                    news.getDType(),
                    news.getDTitle(),
                    sdf.format(news.getDSubdate()),
                    news.getDReadNum(),
                    news.getDPhoto()
                    ));
        }
        return resultList;
    }
    /**
     * 更新浏览量
     * @param key
     * @param newsId
     * @return void
     */
    private void UpdateReadNum(String key,String newsId){
        try {
            if(!redisUtil.hHasKey(key,newsId)){
                redisUtil.hset(key,newsId,0);
            }
            redisUtil.hincr(key,newsId,1);
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

}
